<?php
/**
 *字符串相关
 * @wfs: 2020/10/16
 */
namespace base\other;
use think\facade\Cache;

// use base\other\Strings;
// 创建guid  	 		Strings::uuid();		
// 创建订单号 		Strings::createOrderNo();
// 创建订单号			Strings::createNumber();
// 创建随机字符传	Strings::getRandomStr($len);
// 加密字符串 		Strings::encodeID($no,$len);
// 解密字符串			Strings::decodeID($no);
// 数据脱敏			Strings::dataDesensitization($str,$start = 0, $length ,*);


class Strings {
	
	//密码字典   
    private $dic = array(   
        0=>'0', 1=>'1', 2=>'2', 3=>'3', 4=>'4', 5=>'5', 6=>'6', 7=>'7', 8=>'8',       
        9=>'9', 10=>'A',  11=>'B', 12=>'C', 13=>'D', 14=>'E', 15=>'F',  16=>'G',  17=>'H',       
        18=>'I',19=>'J',  20=>'K', 21=>'L',  22=>'M',  23=>'N', 24=>'O', 25=>'P', 26=>'Q',       
    27=>'R',28=>'S',  29=>'T',  30=>'U', 31=>'V',  32=>'W',  33=>'X', 34=>'Y', 35=>'Z'   
    );  
	
	/* 
	*获取订单号 
	* @return string  2106071808016498
	*/  
	public static function createOrderNo($prefix='')  
	{
		$str = strtoupper(date('ymd')) . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
	   	$str = $prefix.$str;
	   	$cacheStr = Cache::get('base\other\Strings\createOrderNo') ?: [];
	    if( in_array($str,$cacheStr) ) return self::createOrderNo();
	    if( count($cacheStr) > 1000) {
	    	$cacheStr = [$str];
	    }else{
	    	$cacheStr[] = $str;
	    }
	    Cache::set('base\other\Strings\createOrderNo',$cacheStr,1);
	    return $str;
	}
	
	/**
 	* 随机生成n位数字
 	* @return string 生成的字符串
	 */
	public function createNumber($length=8)
	{
		return self::encodeID( self::createOrderNo(), $length );
	}
	
	/**
 	* 随机生成n位字符串
 	* @return string 生成的字符串
	 */
	public static function getRandomStr($n=16){
		$str = "";
	    $str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
	    $max = strlen($str_pol) - 1;
	    for ($i = 0; $i < $n; $i++) {
	        $str .= $str_pol[mt_rand(0, $max)];
	    }
	    return $str;
	}
	
	/**
	 * 获取guid
	 * @param  null
	 */
	public static function uuid() {
	    list($usec, $sec) = explode(" ", microtime(false));
	    $usec = (string)($usec * 10000000);
	    $timestamp = bcadd(bcadd(bcmul($sec, "10000000"), (string)$usec), "621355968000000000");
	    $ticks = bcdiv($timestamp, 10000);
	    $maxUint = 4294967295;
	    $high = bcdiv($ticks, $maxUint) + 0;
	    $low = bcmod($ticks, $maxUint) - $high;
	    $highBit = (pack("N*", $high));
	    $lowBit = (pack("N*", $low));
	    $guid = str_pad(dechex(ord($highBit[2])), 2, "0", STR_PAD_LEFT) . str_pad(dechex(ord($highBit[3])), 2, "0", STR_PAD_LEFT) . str_pad(dechex(ord($lowBit[0])), 2, "0", STR_PAD_LEFT) . str_pad(dechex(ord($lowBit[1])), 2, "0", STR_PAD_LEFT) . "-" . str_pad(dechex(ord($lowBit[2])), 2, "0", STR_PAD_LEFT) . str_pad(dechex(ord($lowBit[3])), 2, "0", STR_PAD_LEFT) . "-";
	    $chars = "abcdef0123456789";
	    for ($i = 0; $i < 4; $i++) {
	        $guid .= $chars[mt_rand(0, 15)];
	    }
	    $guid .= "-";
	    for ($i = 0; $i < 4; $i++) {
	        $guid .= $chars[mt_rand(0, 15)];
	    }
	    $guid .= "-";
	    for ($i = 0; $i < 12; $i++) {
	        $guid .= $chars[mt_rand(0, 15)];
	    }
	    return $guid;
	}
    
    /**
	 * 加密订单号，卡号
	 * @param  null
	 */
    public function encodeID($int, $format=8) {   
        $dics = (new self)->dic;   
        $dnum = 36; //进制数   
        $arr = array ();   
        $loop = true;   
        while ($loop) {   
            $arr[] = $dics[bcmod($int, $dnum)];   
            $int = bcdiv($int, $dnum, 0);   
            if ($int == '0') {   
                $loop = false;   
            }   
        }   
        if (count($arr) < $format)   
            $arr = array_pad($arr, $format, $dics[0]);   
   
        return implode('', array_reverse($arr));   
    }   
   
    /**
	 * 解密订单号，卡号
	 * @param  null
	 */
    public function decodeID($ids) {   
        $dics = (new self)->dic;   
        $dnum = 36; //进制数   
        //键值交换   
        $dedic = array_flip($dics);   
        //去零   
        $id = ltrim($ids, $dics[0]);   
        //反转   
        $id = strrev($id);   
        $v = 0;   
        for ($i = 0, $j = strlen($id); $i < $j; $i++) {   
            $v = bcadd(bcmul($dedic[$id {   
                $i }   
            ], bcpow($dnum, $i, 0), 0), $v, 0);   
        }   
        return $v;   
    } 
	
	
	
	/**
	 * 数据脱敏
	 * @param $string 需要脱敏值
	 * @param int $start 开始
	 * @param int $length 结束
	 * @param string $re 脱敏替代符号
	 * @return bool|string
	 * 例子:
	 * dataDesensitization('18811113683', 3, 4); //188****3683
	 * dataDesensitization('乐杨俊', 0, -1); //**俊
	 */
	public function dataDesensitization($string, $start = 0, $length = 0, $re = '*')
	{
	    if (empty($string)){
	        return false;
	    }
	    $strarr = array();
	    $mb_strlen = mb_strlen($string);
	    while ($mb_strlen) {//循环把字符串变为数组
	        $strarr[] = mb_substr($string, 0, 1, 'utf8');
	        $string = mb_substr($string, 1, $mb_strlen, 'utf8');
	        $mb_strlen = mb_strlen($string);
	    }
	    $strlen = count($strarr);
	    $begin = $start >= 0 ? $start : ($strlen - abs($start));
	    $end = $last = $strlen - 1;
	    if ($length > 0) {
	        $end = $begin + $length - 1;
	    } elseif ($length < 0) {
	        $end -= abs($length);
	    }
	    for ($i = $begin; $i <= $end; $i++) {
	        $strarr[$i] = $re;
	    }
	    if ($begin >= $end || $begin >= $last || $end > $last) return false;
	    return implode('', $strarr);
	}

	
}